package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.OrderConstants;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.BsOrderListDto;
import com.ruoyi.system.domain.ro.OrderCount;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.mapper.BsOrderInfoMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 *
 */
@Service
public class BsOrderInfoServiceImpl extends ServiceImpl<BsOrderInfoMapper, BsOrderInfo>
    implements BsOrderInfoService{

    @Resource
    private BsMenpiaoNumService bsMenpiaoNumService;
    @Resource
    private BsMenpiaoCategoryService bsMenpiaoCategoryService;
    @Resource
    private BsMenpiaoTimeService bsMenpiaoTimeService;
    @Resource
    private BsOrderDetailsService bsOrderDetailsService;
    @Resource
    private BsJingquService bsJingquService;
    @Resource
    private BsUserContractService bsUserContractService;

    @Override
    public List<OrderMenpiaoVo> getDayMenpiaoNum(String date, Long jingquId) {
        List<OrderMenpiaoVo> resultList = new ArrayList<>();
        //根据景区ID获取景区的所有票
        List<BsMenpiaoNum> menpiaoNums = bsMenpiaoNumService.list(new LambdaQueryWrapper<BsMenpiaoNum>().eq(BsMenpiaoNum::getJingquId, jingquId));
        //根据日期和景区ID获取当天的所有订单
        List<BsOrderInfo> orderInfos = getOrderInfoWithDetailsByJingquIdAndDateWithOutCancle(jingquId, date);
        //将所有订单详情保存进集合中
        List<BsOrderDetails> detailsList = new ArrayList<>();
        orderInfos.forEach(x -> detailsList.addAll(x.getOrderDetails()));
        //处理数据，计算出每个种类下的每个时间段的剩余票数
        //通过门票种类进行数据分组，将同一类型的门票数量合并到一个Map下
        Map<Long, List<BsMenpiaoNum>> categoryGroup = menpiaoNums.stream().collect(Collectors.groupingBy(BsMenpiaoNum::getMenpiaoCategoryId));
        Set<Long> categoryIdKey = categoryGroup.keySet();
        //对门票的种类ID进行for循环
        for (Long categoryId : categoryIdKey) {
            OrderMenpiaoVo orderMenpiaoVo = new OrderMenpiaoVo();
            //获取门票类型的详情信息
            BsMenpiaoCategory bsMenpiaoCategoryEntity = bsMenpiaoCategoryService.getById(categoryId);
            orderMenpiaoVo.setMenpiaoCategoryId(categoryId);
            orderMenpiaoVo.setMenpiaoName(bsMenpiaoCategoryEntity.getMenpiaoName());
            orderMenpiaoVo.setMenpiaoNote(bsMenpiaoCategoryEntity.getMenpiaoNote());
            List<OrderMenpiaoTimeAndNumVo> orderMenpiaoTimeAndNumVos = new ArrayList<>();
            for (BsMenpiaoNum bsMenpiaoNum : categoryGroup.get(categoryId)) {
                OrderMenpiaoTimeAndNumVo orderMenpiaoTimeAndNumVo = new OrderMenpiaoTimeAndNumVo();
                //设置门票价格
                orderMenpiaoTimeAndNumVo.setPrice(bsMenpiaoCategoryEntity.getMenpiaoPrice());
                orderMenpiaoTimeAndNumVo.setMenpiaoNumId(bsMenpiaoNum.getMenpiaoNumId());
                //根据门票的信息，查询门票的售出起始时间
                BsMenpiaoTime bsMenpiaoTimeEntity = bsMenpiaoTimeService.getById(bsMenpiaoNum.getMenpiaoTimeId());
                orderMenpiaoTimeAndNumVo.setStartTime(bsMenpiaoTimeEntity.getStartTime());
                orderMenpiaoTimeAndNumVo.setEndTime(bsMenpiaoTimeEntity.getEndTime());
                //计算相同种类下，相同时间段已经卖出的门票数量
                int sellmenpiaonum = detailsList.stream().filter(x -> x.getMenpiaoNumId().equals(bsMenpiaoNum.getMenpiaoNumId())).mapToInt(BsOrderDetails::getOrderNum).sum();
                //剩余门票数，等于当天的门票总数 - 已经售卖出去的门票数
                orderMenpiaoTimeAndNumVo.setRestNum(bsMenpiaoNum.getMenpiaoNum() - sellmenpiaonum);
                orderMenpiaoTimeAndNumVos.add(orderMenpiaoTimeAndNumVo);
            }
            orderMenpiaoVo.setTimeAndNumVos(orderMenpiaoTimeAndNumVos);
            resultList.add(orderMenpiaoVo);
        }
        return resultList;
    }

    @Override
    public BsOrderInfo getOrderInfoWithDetailsByOrderId(Long orderId) {
        return baseMapper.getOrderInfoWithDetailsByOrderId(orderId);
    }

    @Override
    public List<BsOrderInfo> getOrderInfoWithDetailsByJingquIdAndDate(Long jingquId, String date) {
        return baseMapper.getOrderInfoWithDetailsByJingquIdAndDate(jingquId, date);
    }

    @Override
    public List<BsOrderInfo> getOrderInfoWithDetailsByJingquIdAndDateWithOutCancle(Long jingquId, String date) {
        return baseMapper.getOrderInfoWithDetailsByJingquIdAndDateWithOutCancle(jingquId, date);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long genOrder(OrderGenVo orderGenVo) {
        // 保存订单，获取订单的ID
        BsOrderInfo bsOrderInfo = new BsOrderInfo();
        bsOrderInfo.setJingquId(orderGenVo.getJingquId());
        bsOrderInfo.setUserId(SecurityUtils.getUserId());
        bsOrderInfo.setOrderNo(RandomUtils.generate16Number());
        bsOrderInfo.setOrderDate(orderGenVo.getOrderDate());
        bsOrderInfo.setOrderPayStatus(OrderConstants.PAY_STATUS_NO);
        bsOrderInfo.setOrderJudgeStatus(OrderConstants.JUDGE_STATUS_NO);
        bsOrderInfo.setOrderUseStatus(OrderConstants.USER_STATUS_STOP);
        if (save(bsOrderInfo)){
            // 保存订单详情
            List<BsOrderDetails> orderDetailsList = ConvertUtil.sourceToTarget(orderGenVo.getOrderDetails(), BsOrderDetails.class);
            orderDetailsList.forEach(x -> x.setOrderId(bsOrderInfo.getOrderId()));
            bsOrderDetailsService.saveBatch(orderDetailsList);
            return bsOrderInfo.getOrderId();
        }
        return null;
    }

    @Override
    public List<OrderDetailsVo> getOrderDetailsByOrderId(Long orderId) {
        BsOrderInfo orderInfo = getById(orderId);
        List<BsOrderDetails> list = bsOrderDetailsService.list(new LambdaQueryWrapper<BsOrderDetails>().eq(BsOrderDetails::getOrderId, orderId));
        List<OrderDetailsVo> resultList = new ArrayList<>();
        for (BsOrderDetails bsOrderDetails : list) {
            OrderDetailsVo orderDetailsVo = new OrderDetailsVo();
            orderDetailsVo.setOrderDetailsId(bsOrderDetails.getOrderDetailsId());
            BsMenpiaoNum bsMenpiaoNum = bsMenpiaoNumService.getById(bsOrderDetails.getMenpiaoNumId());
            BsMenpiaoTime bsMenpiaoTime = bsMenpiaoTimeService.getById(bsMenpiaoNum.getMenpiaoTimeId());
            orderDetailsVo.setDate(DateUtils.parseDateToStr(DateUtils.YYYY年MM月DD日,orderInfo.getOrderDate()) + " " + DateUtils.parseDateToStr(DateUtils.HH_MM,bsMenpiaoTime.getStartTime()) + "~" + DateUtils.parseDateToStr(DateUtils.HH_MM,bsMenpiaoTime.getEndTime()));
            orderDetailsVo.setOrderNum(bsOrderDetails.getOrderNum());
            orderDetailsVo.setOrderPrice(bsOrderDetails.getOrderPrice());
            BsMenpiaoCategory bsMenpiaoCategory = bsMenpiaoCategoryService.getById(bsMenpiaoNum.getMenpiaoCategoryId());
            orderDetailsVo.setMenpiaoCategoryName(bsMenpiaoCategory.getMenpiaoName());
            resultList.add(orderDetailsVo);
        }
        return resultList;
    }

    @Override
    public MyOrderDetailsVo getOrderAllDetailsByOrderId(Long orderId) {
        MyOrderDetailsVo vo = new MyOrderDetailsVo();
        // 查询订单详情
        BsOrderInfo orderInfo = getById(orderId);
        vo.setOrderUseStatus(orderInfo.getOrderUseStatus());
        vo.setOrderNo(orderInfo.getOrderNo());
        vo.setOrderCreateTime(orderInfo.getCreateTime());
        vo.setOrderPictureCode(orderInfo.getOrderPictureCode());
        vo.setOrderCode(orderInfo.getOrderCode());

        List<PriceDetailsVo> priceDetailsVos = new ArrayList<>();
        List<OrderJingquAndmenpiaoInfoVo> orderJingquAndmenpiaoInfoVos = new ArrayList<>();
        List<BsOrderDetails> orderDetailsList = bsOrderDetailsService.list(new LambdaQueryWrapper<BsOrderDetails>().eq(BsOrderDetails::getOrderId, orderId));
        vo.setTotalPrice(BigDecimal.valueOf(orderDetailsList.stream().mapToDouble(x -> x.getOrderPrice().multiply(BigDecimal.valueOf(x.getOrderNum())).doubleValue()).sum()));
        BsJingqu jingquInfo = bsJingquService.getById(orderInfo.getJingquId());
        for (BsOrderDetails bsOrderDetails : orderDetailsList) {
            BsMenpiaoCategory menpiaoCategoryInfo = bsMenpiaoNumService.getCategoryByNumId(bsOrderDetails.getMenpiaoNumId());
            BsMenpiaoTime menpiaoTimeInfo = bsMenpiaoTimeService.getEntityByNumId(bsOrderDetails.getMenpiaoNumId());
            // 根据订单详情统计费用明细
            PriceDetailsVo priceDetailsVo = new PriceDetailsVo();
            priceDetailsVo.setOrderNum(bsOrderDetails.getOrderNum());
            priceDetailsVo.setOrderPrice(bsOrderDetails.getOrderPrice());
            priceDetailsVo.setMenpiaoCategoryName(menpiaoCategoryInfo.getMenpiaoName());
            priceDetailsVos.add(priceDetailsVo);

            //订单详情
            OrderJingquAndmenpiaoInfoVo orderJingquAndmenpiaoInfoVo = new OrderJingquAndmenpiaoInfoVo();
            orderJingquAndmenpiaoInfoVo.setJingquName(jingquInfo.getJingquName());
            orderJingquAndmenpiaoInfoVo.setLon(jingquInfo.getLon());
            orderJingquAndmenpiaoInfoVo.setLat(jingquInfo.getLat());
            orderJingquAndmenpiaoInfoVo.setJingquAddress(jingquInfo.getJingquAddress());
            orderJingquAndmenpiaoInfoVo.setJingquPictureUrl(jingquInfo.getJingquPictureUrl());
            orderJingquAndmenpiaoInfoVo.setMenpiaoCategoryName(menpiaoCategoryInfo.getMenpiaoName());
            orderJingquAndmenpiaoInfoVo.setMenpiaoNote(menpiaoCategoryInfo.getMenpiaoNote());
            orderJingquAndmenpiaoInfoVo.setOrderStartTime(menpiaoTimeInfo.getStartTime());
            orderJingquAndmenpiaoInfoVo.setOrderCloseTime(menpiaoTimeInfo.getEndTime());
            orderJingquAndmenpiaoInfoVo.setOrderDate(orderInfo.getOrderDate());
            orderJingquAndmenpiaoInfoVo.setOrderNum(bsOrderDetails.getOrderNum());

            // 将所有联系人查询出来
            List<BsUserContract> bsUserContracts = new ArrayList<>();
            if (StringUtils.isNotEmpty(bsOrderDetails.getContractId())){
                String[] contractIdArr = bsOrderDetails.getContractId().split(",");
                for (String s : contractIdArr) {
                    bsUserContracts.add(bsUserContractService.getById(s));
                }
            }
            orderJingquAndmenpiaoInfoVo.setContracts(bsUserContracts);
            orderJingquAndmenpiaoInfoVos.add(orderJingquAndmenpiaoInfoVo);
        }
        vo.setSellName(jingquInfo.getJingquName());
        vo.setOrderCreateTime(orderInfo.getCreateTime());
        vo.setPriceDetailsVos(priceDetailsVos);
        vo.setOrderJingquAndmenpiaoInfoVos(orderJingquAndmenpiaoInfoVos);
        return vo;
    }

    @Override
    public List<BsOrderListDto> getOrderDetailsList(List<BsOrderInfo> list) {
        List<BsOrderListDto> resultList = new ArrayList<>();
        list.forEach(x -> {
            List<OrderDetailsVo> orderDetailsVos = getOrderDetailsByOrderId(x.getOrderId());
            BsOrderListDto bsOrderListDto = ConvertUtil.sourceToTarget(x, BsOrderListDto.class);
            bsOrderListDto.setJingquName(bsJingquService.getById(bsOrderListDto.getJingquId()).getJingquName());
            bsOrderListDto.setJingquPictureUrl(bsJingquService.getById(bsOrderListDto.getJingquId()).getJingquPictureUrl());
            bsOrderListDto.setOrderDetailsVos(orderDetailsVos);
            resultList.add(bsOrderListDto);
        });
        return resultList;
    }

    @Override
    public List<BsOrderInfo> selectOver30NoPayOrder() {
        return baseMapper.selectOver30NoPayOrder();
    }

    @Override
    public List<BsOrderInfo> selectOverTimeOrder() {
        return baseMapper.selectOverTimeOrder();
    }

    @Override
    public int getPeopleCountByDate(int status, String date, Long jingquId) {
        int count = baseMapper.getPeopleCountByDate(status, date, jingquId);
        return count;
    }

    @Override
    public int getPeopleCountByMonth(int status, String month, Long jingquId) {
        return baseMapper.getPeopleCountByMonth(status, month, jingquId);
    }

    @Override
    public int getPeopleCountByYear(int status, String year, Long jingquId) {
        return baseMapper.getPeopleCountByYear(status, year, jingquId);
    }

    @Override
    public int getPeopleCountBySeason(int status, String year,  int season, Long jingquId) {
        return baseMapper.getPeopleCountBySeason(status, year , season, jingquId);
    }

    @Override
    public BigDecimal getCostByMonth(int status, String month, Long jingquId) {
        return baseMapper.getCostByMonth(status, month, jingquId);
    }

    @Override
    public BigDecimal getCostByYear(int status, String year, Long jingquId) {
        return baseMapper.getCostByYear(status, year, jingquId);
    }

    @Override
    public BigDecimal getCostBySeason(int status, String year, int season, Long jingquId) {
        return baseMapper.getCostBySeason(status, year, season, jingquId);
    }

    @Override
    public boolean checkEnoughMenpiaoNum(OrderGenVo orderGenVo) {
        Date date = orderGenVo.getOrderDate();
        for (OrderDetailsGenVo orderDetail : orderGenVo.getOrderDetails()) {
            Integer num = baseMapper.selectMenpiaoNumWithOrder(date, orderDetail.getMenpiaoNumId());
            BsMenpiaoNum menPiaoNum = bsMenpiaoNumService.getById(orderDetail.getMenpiaoNumId());
            if (num == null){
                num = 0;
            }
            int rest = menPiaoNum.getMenpiaoNum() - num;
            if (orderDetail.getOrderNum() > rest){
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean checkAlreadyOrder(OrderGenVo orderGenVo) {
        Long userId = SecurityUtils.getUserId();
        return baseMapper.selectAlreadyOrder(userId, orderGenVo.getOrderDate(), orderGenVo.getJingquId());
    }

    @Override
    public OrderCount orderCount(Long userId) {
        return baseMapper.orderCount(userId);
    }

    @Override
    public List<Future7DaysMenpiaoInfoVo> getFutureMenpiaoNum(Long jingquId) {
        List<Future7DaysMenpiaoInfoVo> resultList = new ArrayList<>();
        List<String> future7DaysDate = DateUtils.getFuture7DaysDate();
        //根据景区ID获取景区的所有票
        List<BsMenpiaoNum> menpiaoNums = bsMenpiaoNumService.list(new LambdaQueryWrapper<BsMenpiaoNum>().eq(BsMenpiaoNum::getJingquId, jingquId));
        int menpiaoSum = menpiaoNums.stream().mapToInt(BsMenpiaoNum::getMenpiaoNum).sum();
        for (int i = 0; i < future7DaysDate.size(); i++) {
            Future7DaysMenpiaoInfoVo vo = new Future7DaysMenpiaoInfoVo();
            //根据日期和景区ID获取当天的所有订单
            List<BsOrderInfo> orderInfos = getOrderInfoWithDetailsByJingquIdAndDateWithOutCancle(jingquId, future7DaysDate.get(i));
            vo.setDate(future7DaysDate.get(i));
            int temOrderNum = orderInfos.stream().mapToInt(x -> x.getOrderDetails().stream().mapToInt(BsOrderDetails::getOrderNum).sum()).sum();
            vo.setMenpiaoNum(menpiaoSum - temOrderNum);
            vo.setTotalMenpiaoNum(menpiaoSum);
            if (i == 0){
                vo.setDayName("今天");
            } else if (i == 1){
                vo.setDayName("明天");
            } else if(i == 2){
                vo.setDayName("后天");
            } else {
                vo.setDayName("");
            }
            resultList.add(vo);
        }
        return resultList;
    }
}




